package com.yjm.test.Spring5.ch5.introductionIntercepor;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.support.DelegatingIntroductionInterceptor;

public class IsModifiedMixin extends DelegatingIntroductionInterceptor implements IsModified {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private boolean isModified = false;
	private Map<Method, Method> setterMap = new ConcurrentHashMap<Method,Method>();
	@Override
	public boolean isModified() {
		return isModified;
	}

	@Override
	public Object invoke(MethodInvocation invocation) throws Throwable {
		if (!isModified) {
			if (invocation.getMethod().getName().startsWith("set") 
					&& invocation.getArguments().length == 1) {
				Method getter = getGetter(invocation.getMethod());
				if (getter != null) {
					Object newValue = invocation.getArguments()[0];
					Object old = getter.invoke(invocation.getThis(), null);
					if (old == null && newValue == null ) {
						isModified = false;
					} else if (old == null && newValue != null) {
						isModified = true;
					} else if (old != null && newValue == null) {
						isModified = true;
					} else {
						isModified = !old.equals(newValue);
					}
				}
			}
		}
		return super.invoke(invocation);
	}
	
	public Method getGetter(Method setter){
		Method getter = setterMap.get(setter);
		if (getter != null) {
			return getter;
		}
		
		String name = setter.getName().replaceFirst("set", "get");
		//getter = setter.getClass().getDeclaredMethod(name, null);
		try {
			getter = setter.getDeclaringClass().getMethod(name, null);
		} catch (NoSuchMethodException | SecurityException e) {
			e.printStackTrace();
		}
		setterMap.put(setter, getter);
		return getter;
	}

}
